; program to search for one string embedded in another
; author:  R. Detmer     revised:  10/97

.386
.MODEL FLAT

ExitProcess PROTO NEAR32 stdcall, dwExitCode:DWORD
INCLUDE io.h

cr          EQU    0dh   ; carriage return character
Lf          EQU    0ah   ; linefeed character

.STACK  4096             ; reserve 4096-byte stack

.DATA
prompt1     BYTE  "String to search?  ", 0
prompt2     BYTE  cr, Lf, "Key to search for?  ", 0
target      BYTE  80 DUP (?)
key         BYTE  80 DUP (?)
trgtLength  DWORD ?
keyLength   DWORD ?
lastPosn    DWORD ?
failure     BYTE  cr,Lf,Lf,"The key does not appear in the string.",cr,Lf,0
success     BYTE  cr,Lf,Lf,'The key appears at position'
position    BYTE  11 DUP (?)
            BYTE  "   in the string.", cr, Lf, 0

PUBLIC _start                       ; make entry point public
.CODE
_start:     output prompt1          ; ask for
            input  target,80        ;   and input target string
            lea    eax, target      ; find length of string
            push   eax              ; length parameter
            call   strlen
            mov    trgtLength,eax   ; save length of target
            output prompt2          ; ask for
            input  key,80           ;   and input key string
            lea    eax, key         ; find length of string
            push   eax              ; length parameter
            call   strlen
            mov    keyLength,eax    ; save length of key

; calculate last position of target to check
            mov    eax,trgtLength 
            sub    eax,keyLength
            inc    eax              ; trgtLength - keyLength + 1
            mov    lastPosn, eax
            cld                     ; left to right comparison

            mov    eax,1            ; starting position
whilePosn:  cmp    eax,lastPosn     ; position <= last_posn?
            jnle   endWhilePosn     ; exit if past last position

            lea    esi,target       ; address of target string
            add    esi,eax          ; add position
            dec    esi              ; address of position to check
            lea    edi,key          ; address of key
            mov    ecx,keyLength    ; number of positions to check
            repe cmpsb              ; check
            jz     found            ; exit on success
            inc    eax              ; increment position
            jmp    whilePosn        ; repeat
endWhilePosn:

            output failure          ; the search failed
            jmp    quit             ; exit

found:      dtoa   position,eax     ; convert position to ASCII
            output success          ; search succeeded
quit:
            INVOKE  ExitProcess, 0  ; exit with return code 0

strlen      PROC    NEAR32
; find length of string whose address is passed on stack
; length returned in EAX
            push    ebp             ; establish stack frame
            mov     ebp, esp
            pushf                   ; save flags
            push    ebx             ; and EBX
            sub     eax, eax        ; length := 0
            mov     ebx, [ebp+8]    ; address of string
whileChar:  cmp     BYTE PTR [ebx], 0  ; null byte?
            je      endWhileChar    ; exit if so
            inc     eax             ; increment length
            inc     ebx             ; point at next character
            jmp     whileChar       ; repeat
endWhileChar:
            pop     ebx             ; restore registers and flags
            popf 
            pop     ebp
            ret     4               ; return, discarding parameter
strlen      ENDP

            END

